
#ifndef etl_string_h
#define etl_string_h

#include "etl_list.h"

#include <string>
#include <string.h>

namespace etl
{

class etl_string
{
 public:

  /// Default constructor
  etl_string();

  /// Copy constructor
  /// \param obj The object we construct ourselves from.
  etl_string( const etl_string& obj );

  /// C string constructor
  /// \param s The C string to construct ourselves from.
  etl_string( const char* s );

  /// Construct ourselves as a string rep of the given number and base.
  /// \param lv The number to construct ourselves from.
  /// \param b The base to use for our string representation.
  etl_string( long lv, int b = 10 );

  /// Construct ourselves as a string rep of the given number and base.
  /// \param ulv The number to construct ourselves from.
  /// \param b The base to use for our string representation.
  etl_string( unsigned long ulv, int b = 10 );

  /// Construct ourselves as a string rep of the given number and base.
  /// \param dv The number to construct ourselves from.
  etl_string( double dv );

  /// Virtual destructor
  virtual ~etl_string();

  /// Returns the C style internal string representation.
  const char* c_str() const;

  /// Assignment operator
  /// \param obj The source object to copy from.
  etl_string& operator = ( const etl_string& obj );

  /// Assignment operator (C string)
  /// \param new_string The C style string to copy from.
  etl_string& operator = ( const char* new_string );

  /// Equality operator
  /// \param obj The object to compare our equality to.
  bool operator == (const etl_string& obj);

  /// Equality operator
  /// \param obj The C string to compare our equality to.
  bool operator == (const char* obj);

  /// Inequality operator
  /// \param obj The object to compare our inequality to.
  bool operator != (const etl_string& obj);

  /// Returns true if the internal string ends with the passed string.
  /// \param obj The C style string to compare against the end of the internal string.
  bool ends_with( const char* obj );

  /// Returns true if the internal string begins with the passed string.
  /// \param obj The C style string to compare against the beginning of the internal string.
  bool begins_with( const char* obj );

  /// Returns true if the internal string contains the passed string.
  /// \param obj The C style string to check our internal string for.
  bool contains( const char* obj );

  /// printf() style string formatting.
  /// \param format A sprintf() compatible C format string.
  /// \param ... Variable arguments for the C style format string.
  int format_in_place(char* f, ...);

  static etl_string format( char* f, ... );

  etl_string operator +(const etl_string& obj);
  etl_string operator +(const char* c_string);
  etl_string& operator +=(const etl_string& obj);
  etl_string& operator +=(const char* c_string);
  etl_string sub_string(int index, int length);
  int split(char delim, etl_list<etl_string>& parts);
  int split(etl_string delim, etl_list<etl_string>& parts);
  int munch(int len);
  int trim();
  int clip();
  int trim_and_clip();
  int remove(char toBeRemoved);
  int cond_chomp(etl_string match);
  unsigned long length() const;
  int from_long(long lv,int base = 10);
  int from_ulong(unsigned long lv,int base = 10);
  int from_double(double dv);
  long to_long(int base = 10);
  unsigned long to_ulong(int base = 10);
  int to_lower();
  int to_upper();
  double to_double();
  static etl_string to_base64( unsigned char* data, long len );
  long from_base64( unsigned char** dest );
  int match( char* regexp );
  int find( etl_string subString, int pos = 0 );
  int rfind( etl_string subString, int pos = std::string::npos );

private:
  etl_string& copy(const char* new_string);
  static char encode_byte( unsigned char u );
  static unsigned char decode_char( char c );
  int match_here( char* regexp, const char* text );
  int match_star( int c, char* regexp, const char* text );

  std::string internalString;
};

}

#endif
